#include <jni.h>
#include <string>
#include <android/log.h>

#define TAG "DynamicNative"

extern "C" JNIEXPORT jstring

JNICALL
Java_com_yxf_dynamicnative_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

static void logD(const char *str) {
    __android_log_write(ANDROID_LOG_DEBUG, str, TAG);
}

static void logE(const char *str) {
    __android_log_write(ANDROID_LOG_ERROR, str, TAG);
}

static bool registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods) {
    jclass clazz;
    clazz = env->FindClass(className);
    if (clazz == NULL) {
        logE("the class we found is null , class name : ");
        logE(className);
        return false;
    }
    if (methods == NULL) {
        logE("the methods is null");
        return false;
    }
    int methodCount = sizeof(*methods) / sizeof(methods[0]);
    int result = env->RegisterNatives(clazz, methods, methodCount);
    char message[1024];
    sprintf(message, "result : %d", result);
    logD(message);
    if (result == JNI_OK) {
        return true;
    } else {
        return false;
    }
}

static jstring getRepeatString(JNIEnv *env, jobject obj, jstring string_, jint repeatCount) {
    using namespace std;
    const char *str = env->GetStringUTFChars(string_, 0);
    string cStr = string(str);
    string result;
    for (int i = 0; i < repeatCount; ++i) {
        result = result + cStr;
    }
    env->ReleaseStringUTFChars(string_, str);
    return env->NewStringUTF(result.c_str());
}

static JNINativeMethod methods[] = {
        //Java Invoke C.
        {"getRepeatString", "(Ljava/lang/String;I)Ljava/lang/String;", (void *) getRepeatString},
};

static const char *classPath = "com/yxf/dynamicnative/MainActivity";

jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    //获得JNIEnv对象
    void *env = NULL;
    if (vm->GetEnv(&env, JNI_VERSION_1_6) != JNI_OK) {
        logE("get JNIEnv failed ,register methods failed");
        return -1;
    }
    //注册
    if (registerNativeMethods((JNIEnv *) env, classPath, methods) != JNI_TRUE) {
        logE("register methods failed");
    } else {
        logD("register methods successfully");
    }
    return JNI_VERSION_1_6;
}